const EPSILON = 1e-10;

// See https://hal.inria.fr/hal-02189483 appendix C.2 Orientation test
const _matrix = new BABYLON.Matrix();
export function orient3D(a: BABYLON.Vector3, b: BABYLON.Vector3, c: BABYLON.Vector3, d: BABYLON.Vector3) {
  _matrix.setRowFromFloats(0, a.x, a.y, a.z, 1);
  _matrix.setRowFromFloats(1, b.x, b.y, b.z, 1);
  _matrix.setRowFromFloats(2, c.x, c.y, c.z, 1);
  _matrix.setRowFromFloats(3, d.x, d.y, d.z, 1);

  const det = _matrix.determinant();

  if (det > EPSILON) {
    return 1;
  } else if (det < -EPSILON) {
    return -1;
  }
  return 0;
}

export function frontSide(a: BABYLON.Vector3, b: BABYLON.Vector3, c: BABYLON.Vector3, d: BABYLON.Vector3) {
  return orient3D(d, b, c, a);
}

export function sameSide(a: BABYLON.Vector3, b: BABYLON.Vector3, c: BABYLON.Vector3, d: BABYLON.Vector3, e: BABYLON.Vector3) {
  return (orient3D(a, b, c, d) > 0) === (orient3D(a, b, c, e) > 0);
}

export function calcFaceArea(p0: BABYLON.Vector3, p1: BABYLON.Vector3, p2: BABYLON.Vector3): number {
  let area: number = 0.0;
  let crossVec = BABYLON.Vector3.Cross(p1.subtract(p0), p2.subtract(p0));
  area = crossVec.length() * 0.5;
  return area;
}

export function calcFaceNormal(p0: BABYLON.Vector3, p1: BABYLON.Vector3, p2: BABYLON.Vector3): BABYLON.Vector3 {
  return BABYLON.Vector3.Cross(p0.subtract(p1), p2.subtract(p0)).normalize();
}